<!DOCTYPE html>
<html lang="zh-cn">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>在线词云图生成</title>
    <script src="js/d3.v7.min.js"></script>
    <script src="js/d3.layout.cloud.js"></script>
    <script src="js/FileSaver.min.js"></script>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            font-family: 'Segoe UI', system-ui, sans-serif;
        }

        body {
            background: #f0f2f5;
            min-height: 100vh;
            padding: 2rem;
        }

        .container {
            max-width: 90%;
            margin: 0 auto;
            background: white;
            border-radius: 1rem;
            box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
            overflow: hidden;
        }

        .app-header {
            background: #2196F3;
            color: white;
            padding: 1.5rem;
            text-align: center;
        }

        .content {
            display: flex;
            flex-direction: row;
            gap: 1.8rem;
            padding: 1.8rem;
            width: 100%;
            height: 550px;
        }

        .form {
            flex: 1;
            min-width: 200px;
        }

        textarea {
            width: 100%;
            height: 424px;
            margin-bottom: 20px;
            padding: 15px;
            border: 1px solid #ccc;
            border-radius: 8px;
            font-size: 14px;
            resize: none;
            box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1);
        }

        textarea:focus {
            outline: none;
        }

        .buttons {
            display: flex;
            justify-content: space-between;
            gap: 10px;
        }

        button {
            width: 100%;
            padding: 12px;
            font-size: 16px;
            color: #fff;
            background-color: #007bff;
            border: none;
            border-radius: 8px;
            cursor: pointer;
            transition: background-color 0.3s ease;
        }

        button:hover {
            background-color: #0056b3;
        }

        .generate {
            flex: 2;
        }

        .exportPNG {
            flex: 1;
        }

        .chart {
            flex: 2;
            display: flex;
            justify-content: center;
            align-items: center;
            background-color: #f9f9f9;
        }

        #word-cloud {
            width: 100%;
            height: 100%;
            border: 1px solid #ddd;
            background-color: #fff;
            border-radius: 8px;
            box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
            display: flex;
            justify-content: center;
            align-items: center;
        }

        svg {
            display: block;
        }
    </style>
</head>

<body>
    <div class="container">
        <header class="app-header">
            <h1>在线词云图生成</h1>
        </header>
        <div class="content">
            <div class="form">
                <textarea id="text" placeholder="请输入单词和权重（格式：word: size，每行一个）"></textarea>
                <div class="buttons">
                    <button id="generate" class="generate">生成词云</button>
                    <button id="exportPNG" class="exportPNG">导出图片</button>
                </div>

            </div>
            <div class="chart">
                <div id="word-cloud">
                    <p style="color: #aaa;">词云将在这里显示</p>
                </div>
            </div>
        </div>
    </div>
    <script>
        // 解析输入文本为词云数据
        function parseTextToWords(text) {
            const lines = text.trim().split('\n');
            return lines
                .map(line => {
                    const parts = line.split(/[:：|]/);
                    if (parts.length !== 2) return null; // 检查格式是否正确
                    const word = parts[0].trim();
                    const size = parseInt(parts[1].trim());
                    if (!word || isNaN(size)) return null; // 检查单词和权重是否有效
                    return { text: word, size: size };
                })
                .filter(item => item !== null); // 过滤掉无效的输入
        }

        // 生成词云
        function generateWordCloud() {
            const text = document.getElementById('text').value; // 获取输入文本
            const words = parseTextToWords(text);

            if (words.length === 0) {
                alert('请输入有效的单词和权重（格式：word: size，每行一个）');
                return;
            }

            // 清空之前的词云
            d3.select("#word-cloud").selectAll("*").remove();

            // 定义词云布局
            const layout = d3.layout.cloud()
                .size([600, 400]) // 设置画布大小
                .words(words) // 绑定词云数据
                .padding(5) // 设置单词之间的间距
                .rotate(() => (Math.random() > 0.5 ? 0 : 90)) // 随机旋转单词
                .font("Impact") // 设置字体
                .fontSize(d => d.size) // 根据数据中的 size 字段设置字体大小
                .on("end", draw); // 布局计算完成后调用 draw 函数绘制词云

            // 启动布局计算
            layout.start();

            // 渲染词云到 SVG
            function draw(words) {
                d3.select("#word-cloud") // 选择词云容器
                    .append("svg") // 添加 SVG 元素
                    .attr("width", layout.size()[0]) // 设置 SVG 宽度
                    .attr("height", layout.size()[1]) // 设置 SVG 高度
                    .append("g") // 添加 g 元素，用于分组
                    .attr("transform", `translate(${layout.size()[0] / 2},${layout.size()[1] / 2})`) // 将 g 元素移动到画布中心
                    .selectAll("text") // 选择所有 text 元素
                    .data(words) // 绑定词云数据
                    .enter() // 创建对应数量的 text 元素
                    .append("text") // 添加 text 元素
                    .style("font-family", "Impact") // 设置字体
                    .style("fill", () => `hsl(${Math.random() * 360}, 70%, 50%)`) // 随机设置颜色
                    .attr("text-anchor", "middle") // 设置文本对齐方式为居中
                    .attr("transform", d => `translate(${[d.x, d.y]})rotate(${d.rotate})`) // 设置文本位置和旋转角度
                    .text(d => d.text) // 设置文本内容
                    .style("font-size", d => `${d.size}px`); // 设置字体大小
            }
        }

        // 导出为PNG 
        function exportAsPNG() {
            const svg = document.querySelector('#word-cloud svg');
            const svgData = new XMLSerializer().serializeToString(svg);
            const canvas = document.createElement('canvas');

            canvas.width = 800;
            canvas.height = 600;
            const ctx = canvas.getContext('2d');

            const img = new Image();
            img.onload = () => {
                ctx.drawImage(img, 0, 0);
                canvas.toBlob(blob => {
                    saveAs(blob, 'wordcloud.png');
                });
            };
            img.src = 'data:image/svg+xml;base64,' + btoa(svgData);
        }

        // 绑定按钮点击事件
        document.getElementById('generate').addEventListener('click', generateWordCloud);
        document.getElementById('exportPNG').addEventListener('click', exportAsPNG);
    </script>
</body>

</html>